package com.nxj.sqlSession;

import com.nxj.pojo.Configuration;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;

public class DefaultSqlSession implements SqlSession {

    private Configuration configuration;

    private Executor simpleExecutor;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
        this.simpleExecutor = new SimpleExecutor();
    }

    @Override
    public <E> List<E> selectList(String statementId, Object... params) throws Exception {
        return simpleExecutor.query(configuration, configuration.getMappedStatementMap().get(statementId), params);
    }

    @Override
    public <T> T selectOne(String statementId, Object... params) throws Exception {
        return simpleExecutor.queryForObject(configuration, configuration.getMappedStatementMap().get(statementId), params);
    }

    public boolean deleteByCondition(String statementId, Object... params) throws Exception {
        return simpleExecutor.deleteByCondition(configuration, configuration.getMappedStatementMap().get(statementId), params);
    }

    public int updateByCondition(String statementId, Object... params) throws Exception {
        return simpleExecutor.updateByCondition(configuration, configuration.getMappedStatementMap().get(statementId), params);
    }

    public boolean insertOneObject(String statementId, Object... params) throws Exception {
        return simpleExecutor.insertOneObject(configuration, configuration.getMappedStatementMap().get(statementId), params);
    }

    @Override
    public <T> T getMapper(Class<T> mapperClass) {
        return (T) Proxy.newProxyInstance(mapperClass.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String methodName = method.getName();
                String className = method.getDeclaringClass().getName();
                String statementId = (className + "." + methodName);
                // 这个的关键就是通过不同的方法 匹配不同的底层执行器实现 (死办法就是写死 但是这样肯定不行的， 通过返回值也是不行的 也是没办法解决的)
                // 先写死 看看有没有其他的解决方案
                switch (methodName) {
                    case "findAll":
                        return selectList(statementId, args);
                    case "findByCondition":
                        return selectOne(statementId, args);
                    case "insertOneObject":
                        return insertOneObject(statementId, args);
                    case "updateByCondition":
                        return updateByCondition(statementId, args);
                    case "deleteByCondition":
                        return deleteByCondition(statementId, args);
                    default:
                        throw new RuntimeException("未匹配执行器，请确认");
                }
            }
        });
    }

    @Override
    public void close() throws Exception {
        simpleExecutor.close();
    }
}
